#include "util.h"


// CRC16-CCITT多项式
#define CRC16_CCITT_POLY 0x1021
// CRC16-CCITT初始值
#define CRC16_CCITT_INIT 0
// 计算CRC16-CCITT校验码
uint16_t calculate_crc16(const uint8_t *data, size_t length) {
    uint16_t crc = CRC16_CCITT_INIT;
    // 处理每个字符
    for (size_t i = 0; i < length; i++) {
        // 将数据字节左移8位与CRC值异或
        crc ^= (uint16_t)(data[i] << 8);
        // 对每个位进行处理
        for (int j = 0; j < 8; j++) {
            // 如果最高位为1，左移后与多项式异或
            if (crc & 0x8000) {
                crc = (crc << 1) ^ CRC16_CCITT_POLY;
            }
            else{
            // 如果最高位为0，只需左移
                crc <<= 1;
            }
        }
    }
    return crc;
}

// 计算校验和，使用CRC16
int calculate_checksum(Frame *frame) {
    // 创建一个临时缓冲区，包含所有需要计算CRC的数据
    uint8_t buffer[sizeof(uint8_t) * 5 + FRAME_PAYLOAD_SIZE];
    int offset = 0; // 偏移量
    
    // 将帧的关键字段复制到缓冲区
    buffer[offset++] = frame->seq_num;
    buffer[offset++] = frame->ack_num;
    buffer[offset++] = frame->is_ack;
    buffer[offset++] = frame->checksum;
    buffer[offset++] = frame->send_id;
    buffer[offset++] = frame->recv_id;
    memcpy(buffer + offset, frame->data, FRAME_PAYLOAD_SIZE);
    
    // 计算CRC16校验和
    return calculate_crc16(buffer, offset + FRAME_PAYLOAD_SIZE);
}

// 计算 CRC 校验和的示例实现
int compute_crc(const char *data, int length) {
    //添加一个特殊的情况
    if (data == NULL || length <= 0) {
        return 0; // 返回默认值
    }
    int crc = 0;
           
      // 如果是 ACK 帧，只计算固定的前 N 个字段（例如前 8 个字节）
    if (data[2] == 1) { // 通过 data[2] 提取 is_ack 的值
        // 如果是 ACK 帧，只计算前 8 字节（头部）
        // printf("我倒是看看你是不是狗屎: %u\n", data[2]);
        for (int i = 0; i < HEADER_SIZE; i++) { // 只计算 seq_num 到 recv_id 的部分
            if (i == 3 || i == 4) continue; // 跳过 checksum 字段
            crc ^= data[i];
        }
    }
    else{
        for (int i = 0; i < length; i++) {
        crc ^= data[i];  // 简单异或操作
    }

    }
    
    return crc;
}
// 计算 CRC 校验和的示例实现


//Linked list functions
int ll_get_length(LLnode *head)
{
    int count = 0;
    LLnode *current = head;
    while (current->next != head) {
        current = current->next;
        count++;
    }
    return count;
}

void ll_append_node(LLnode *head_ptr,  void *value)
{
    //创建一个node结点
    LLnode *node = (LLnode *) malloc(sizeof(LLnode));
    node->value = value;

    //双向循环链表的尾插法
    node->next = head_ptr;
    node->prev = head_ptr->prev;
    head_ptr->prev = node;
    node->prev->next = node;
}


LLnode *ll_pop_node(LLnode *head_ptr) //传入双向链表头结点
{
    LLnode *node = NULL;
    if (head_ptr->next != head_ptr) {
        node = head_ptr->next;
        head_ptr->next = node->next;
        node->next->prev = head_ptr;
        //清空node中的痕迹
        node->next = node;
        node->prev = node;
        
        return node;  //弹出来
    }
    fprintf(stdout, "链表为空\n"); 
    return NULL;
}

//Compute the difference in usec for two timeval objects
long timeval_usecdiff(struct timeval *start_time,  struct timeval *finish_time)
{
  long usec;
  usec=(finish_time->tv_sec - start_time->tv_sec)*1000000;
  usec+=(finish_time->tv_usec- start_time->tv_usec);
  return usec;
}


//Print out messages entered by the user
void print_cmd(Cmd * cmd)
{
    fprintf(stderr, "src=%d, dst=%d, message=%s\n", 
           cmd->src_id,
           cmd->dst_id,
           cmd->message);
}


char * convert_frame_to_char(Frame * frame)
{
    //TODO: You should implement this as necessary
   // 分配最大帧大小的缓冲区
    char * char_buffer = (char *) malloc(MAX_FRAME_SIZE);
    if (!char_buffer) {
        perror("Malloc failed in convert_frame_to_char");
        exit(1);
    }
    // 清空缓冲区
    memset(char_buffer, 0, MAX_FRAME_SIZE);

    // 将 Frame 的字段逐一拷贝到 char_buffer
    int offset = 0;

    // 复制 seq_num
    memcpy(char_buffer + offset, &frame->seq_num, sizeof(frame->seq_num));
    offset += sizeof(frame->seq_num);

    // 复制 ack_num
    memcpy(char_buffer + offset, &frame->ack_num, sizeof(frame->ack_num));
    offset += sizeof(frame->ack_num);

    // 复制 is_ack
    memcpy(char_buffer + offset, &frame->is_ack, sizeof(frame->is_ack));
    offset += sizeof(frame->is_ack);

    // 复制 checksum
    memcpy(char_buffer + offset, &frame->checksum, sizeof(frame->checksum));
    offset += sizeof(frame->checksum);

    // 复制 send_id
    memcpy(char_buffer + offset, &frame->send_id, sizeof(frame->send_id));
    offset += sizeof(frame->send_id);

    // 复制 recv_id
    memcpy(char_buffer + offset, &frame->recv_id, sizeof(frame->recv_id));
    offset += sizeof(frame->recv_id);

    //memcpy(char_buffer + offset, frame->data, FRAME_PAYLOAD_SIZE);
    snprintf(char_buffer + offset, FRAME_PAYLOAD_SIZE, "%s", frame->data);

    return char_buffer;
}


Frame * convert_char_to_frame(char * char_buf)
{
    //TODO: You should implement this as necessary
    // 分配一个 Frame 结构
    Frame * frame = (Frame *) malloc(sizeof(Frame));
    if (!frame) {
        perror("Malloc failed in convert_char_to_frame");
        exit(1);
    }

    // 初始化 Frame 数据
    memset(frame, 0, sizeof(Frame));

    // 逐一解析字段
    int offset = 0;

    // 解析 seq_num
    memcpy(&frame->seq_num, char_buf + offset, sizeof(frame->seq_num));
    offset += sizeof(frame->seq_num);

    // 解析 ack_num
    memcpy(&frame->ack_num, char_buf + offset, sizeof(frame->ack_num));
    offset += sizeof(frame->ack_num);

    // 解析 is_ack
    memcpy(&frame->is_ack, char_buf + offset, sizeof(frame->is_ack));
    offset += sizeof(frame->is_ack);

    // 解析 checksum
    memcpy(&frame->checksum, char_buf + offset, sizeof(frame->checksum));
    offset += sizeof(frame->checksum);

    // 解析 send_id
    memcpy(&frame->send_id, char_buf + offset, sizeof(frame->send_id));
    offset += sizeof(frame->send_id);

    // 解析 recv_id
    memcpy(&frame->recv_id, char_buf + offset, sizeof(frame->recv_id));
    offset += sizeof(frame->recv_id);

    // 解析 data
    snprintf(frame->data, FRAME_PAYLOAD_SIZE, "%s", char_buf + offset);
    //memcpy(frame->data, char_buf + offset, FRAME_PAYLOAD_SIZE);

    return frame;
}
